//% color="#6495ED" iconWidth=50 iconHeight=40
namespace cv_collect_train_inference{
    //% block="采集数据集" blockType="tag"
    export function tagtest() {}
    //% block="初始化摄像头直到成功 编号[CAMNUM]" blockType="command"
    //% CAMNUM.shadow="number" CAMNUM.defl="0"
    export function cv_collect_init(parameter: any, block: any) {
        let num=parameter.CAMNUM.code;
        Generator.addImport(`import time\nimport cv2\nimport numpy as np`)   
        Generator.addCode(`cv_collect_cap = cv2.VideoCapture(${num})`)          
    Generator.addCode(`while not cv_collect_cap.isOpened():
    continue`)    
    }
    //% block="创建窗口[TEXT]并设置为全屏" blockType="command"
    //% TEXT.shadow="string" TEXT.defl="cvwindow"
    export function cv_collect_set_winname(parameter: any, block: any) {
        let text=parameter.TEXT.code;
        Generator.addCode(`cv2.namedWindow(${text},cv2.WND_PROP_FULLSCREEN)`)
        Generator.addCode(`cv2.setWindowProperty(${text}, cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)`)
    }
    //% block="设置采集图片的尺寸为[RESIZE]" blockType="command"
    //% RESIZE.shadow="dropdown" RESIZE.options="RESIZE"

    export function cv_collect_collect_RESIZE(parameter: any, block: any) {
        let resize=parameter.RESIZE.code;

        if (`${resize}` === '1') {
        Generator.addCode(`img_src_x =240\nimg_src_y = 320`)
        }else if (`${resize}` === '2') {
        Generator.addCode(`img_src_x =100\nimg_src_y = 100`)
        }else if (`${resize}` === '3') {
        Generator.addCode(`img_src_x =200\nimg_src_y = 200`)
        }
    }
    //% block="打开摄像头画面并读取一帧" blockType="command"

    export function cv_collect_collect_img(parameter: any, block: any) {

        Generator.addImport(`from create_dataset import *`)
        Generator.addInit("saveImage1",`dataset_creator = DatasetCreator()`)
        Generator.addCode(`img_src = dataset_creator.display_image(cv_collect_cap,img_src_x,img_src_y)`)
        }
    //% block="数据划分 训练集[TRAIN] 验证集[VAL] 测试集[TEST]" blockType="command"
    //% TRAIN.shadow="number" TRAIN.defl="0.7"
    //% VAL.shadow="number" VAL.defl="0.2"
    //% TEST.shadow="number" TEST.defl="0.1"
    export function cv_collect_partition_data(parameter: any, block: any) {
        let train=parameter.TRAIN.code;
        let val=parameter.VAL.code;
        let test=parameter.TEST.code;
        Generator.addImport(`from create_dataset import *`)
        Generator.addInit("saveImage1",`dataset_creator = DatasetCreator()`)
        Generator.addCode(`
train_ratio_value = ${train}
valid_ratio_value = ${val}
test_ratio_value = ${test}
`)

    }


    //% block="采集[PIC]张图片数据到文件夹 路径[PATH],标签名[BQ]" blockType="command"
    //% PATH.shadow="string" PATH.defl="/root/mydataset"
    //% PIC.shadow="number"    PIC.defl=50
    //% NAME.shadow="number" NAME.defl="0"
    //% BQ.shadow="string" BQ.defl="class_name"
    export function cv_collect_collect_data(parameter: any, block: any) {
        let path=parameter.PATH.code;
        let pic=parameter.PIC.code;
        let bq=parameter.BQ.code;
    
        Generator.addImport(`from create_dataset import *`)
        Generator.addInit("saveImage1",`dataset_creator = DatasetCreator()`)
        Generator.addCode(`dataset_creator.create_file(r${path},${bq})`)
        Generator.addCode(`dataset_creator.collect_and_sort_images(${bq},img_src, ${pic}, train_ratio_value, valid_ratio_value, test_ratio_value)`)
    }
    //% block="删除位于 [PATH] 文件夹中的图片文件，其标签名为 [FILE]" blockType="command"
    //% PATH.shadow="string" PATH.defl="/root/mydataset"
    //% FILE.shadow="string" FILE.defl="class_name"
    export function cv_collect_clear_category(parameter: any, block: any) {
        let path=parameter.PATH.code;
        let file=parameter.FILE.code;
   
        Generator.addImport(`from create_dataset import *`)
        Generator.addInit("saveImage1",`dataset_creator = DatasetCreator()`)
        Generator.addCode(`dataset_creator.clear_category_images(r${path}, ${file})`)
    }
    
    //% block="删除位于 [PATH] 文件夹中的目录，其标签名为 [FILE]" blockType="command"
    //% PATH.shadow="string" PATH.defl="/root/mydataset"
    //% FILE.shadow="string" FILE.defl="class_name"
    export function cv_collect_clear_images(parameter: any, block: any) {
        let path=parameter.PATH.code;
        let file=parameter.FILE.code;

        Generator.addImport(`from create_dataset import *`)
        Generator.addInit("saveImage1",`dataset_creator = DatasetCreator()`)
        Generator.addCode(`dataset_creator.clear_category(r${path}, ${file})`)
    }

    //% block="数据处理" blockType="tag"
    export function tagtestc() {}
    //% block="对图像数据[DATA]转换成展平数组" blockType="command"
    //% DATA.shadow="normal" DATA.defl="data"
 
    export function transform_data(parameter: any, block: any) {

        let data=parameter.DATA.code;
        Generator.addImport(`import numpy as np`)
        Generator.addInit("transform_data",`data_list = []`)
        Generator.addCode(`data_list.append(${data})`)
        Generator.addCode(`transform_data_value = np.concatenate(data_list).reshape(len(data_list), -1)`)

    }
    //% block="图片特征数据" blockType="reporter"
    export function transform_data_value(parameter: any, block: any) {

        Generator.addCode(`transform_data_value`)
    }
    //% block="将图片特征数据[DATA]记录在CSV文件[CSV]内,定义标签编码[LABEL]" blockType="command"
    //% DATA.shadow="normal" DATA.defl=transform_data_value
    //% CSV.shadow="string" CSV.defl="mydata.csv"
    //% LABEL.shadow="number" LABEL.defl="0"
    export function transform_data_write(parameter: any, block: any) {

        let csv=parameter.CSV.code;
        let data=parameter.DATA.code;
        let label=parameter.LABEL.code;
        Generator.addImport(`import csv`)
        Generator.addCode(`header = ["Path_Filename"] + [f"Feature {i+1}" for i in range(len(${data}[0]))] + ["Label"]
csv_data = []
start_index = 0
existing_rows = []

if os.path.exists(${csv}):
    with open(${csv}, 'r', encoding='UTF8') as f:
        existing_rows = list(csv.reader(f))
        if len(existing_rows) > 1:
            last_row = existing_rows[-1]
            last_index = int(last_row[0].split('.')[0])
        start_index = last_index + 1

for i in range(len(${data})):
    row_data = ${data}[i].tolist().copy();  
    row_data.append(${label})
    row_data.insert(0, str(start_index + i) + ".png")
    csv_data.append(row_data)

with open(${csv}, 'a', encoding='UTF8', newline='') as f:
    writer = csv.writer(f)
    if len(existing_rows)==0:
        writer.writerow(header) 
        writer.writerows(csv_data)`)
    }
    //% block="训练模型（PC端）" blockType="tag"
    export function tagtesta() {}
    //% block="初始化MMEdu模块,选择[MMDEU]模块,设置[MODEL]模型" blockType="command" 
    //% MMDEU.shadow="dropdown"   MMDEU.options="MMDEU"
    //% MODEL.shadow="dropdown"   MODEL.options="MODEL"
    export function MMEdu_Init(parameter: any, block: any){
        let MMDEU = parameter.MMDEU.code
        let model = parameter.MODEL.code
      
        Generator.addImport(`from MMEdu import ${MMDEU} as mmdeu_cls_det`)
        Generator.addImport("import os")
        Generator.addImport("import time")
        Generator.addCode(`mmdeu_model = mmdeu_cls_det("${model}")`)
        Generator.addCode(`mmdeu_model.cfg.checkpoint_config.max_keep_ckpts=1`)

}
    //% block="指定数据集中的类别数量[NUMBER]" blockType="command"
    //% NUMBER.shadow="normal"   NUMBER.defl="3"
    export function MMEdu_Init_ncl(parameter: any, block: any){
        let number = parameter.NUMBER.code
        Generator.addCode(`mmdeu_model.num_classes = ${number}`)
    }


    //% block="从指定数据集路径中加载数据[PATH]" blockType="command"
    //% PATH.shadow="string"   PATH.defl="/path/to/dataset"
    export function MMEdu_Init_loaddata(parameter: any, block: any){
        let path = parameter.PATH.code

        Generator.addCode(`mmdeu_model.load_dataset(path=${path})`)
    }

    //% block="设置模型的保存路径[PATH]" blockType="command"
    //% PATH.shadow="string"   PATH.defl="/path/to/cls"
    export function MMEdu_Init_sf(parameter: any, block: any){
        let path = parameter.PATH.code
        Generator.addCode(`
if not os.path.exists(${path}):
    print("The folder does not exist,created automatically")
    os.makedirs( ${path})
 
mmdeu_model.save_fold = ${path}`)
    }

    //% block="训练模型，设置参数训练[NUM]次, 选择[OPT]优化器,学习率[LR],预训练权重文件加载路径[CP]" blockType="command"
    //% NUM.shadow="normal" NUM.defl="10"
    //% OPT.shadow="dropdown" OPT.options="OPT"
    //% LR.shadow="normal" LR.defl="0.01"
    //% CP.shadow="normal" CP.defl=None
    export function MMEdu_Init_train(parameter: any, block: any) {
        let NUM = parameter.NUM.code
        let OPT = parameter.OPT.code
        let LR = parameter.LR.code
        let CP = parameter.CP.code
        if (`${CP}` === "None" ) {
            CP = "None"
        }else { 
            CP = `r"${CP}"`}
        Generator.addCode(`
try:
    mmdeu_model.train(epochs=${NUM}, validate=True, optimizer="${OPT}", lr=${LR}, checkpoint=${CP})
except:
    pass
`) 
}

    //% block="模型转换（PC端）" blockType="tag"
    export function tagtest1() {}
    //% block="设置模型转换参数[CONFIGA]为[VAL]" blockType="command"
    //% CONFIGA.shadow="dropdown"   CONFIGA.options="CONFIGA"
    //% VAL.shadow="string"   VAL.defl=" "
    export function MMEdu_Init_mc(parameter: any, block: any){
        
        let CONFIGA = parameter.CONFIGA.code
        let VAL = parameter.VAL.code
        Generator.addImport("from MMEdu import MMClassification as cls")
        Generator.addImport("import os\nimport glob\npara_model_convert = {}")
    
 
        if (`${CONFIGA}` === "checkpoint") {
            Generator.addCode(`
CONFIG = "${CONFIGA}"  
VAL = r${VAL}
if CONFIG == "checkpoint":
    pattern = os.path.join(VAL, 'best_accuracy*.pth')
    matching_files = glob.glob(pattern)
    if matching_files:
        para_model_convert[CONFIG] = matching_files[0]  
    else:
        print("No matching .pth file found in the specified directory.")
`)
        }
        else {

            Generator.addCode(`
output_directory = os.path.dirname(${VAL})
if not output_directory:
    output_directory = '.'
if not os.path.exists(output_directory):
    print("The folder does not exist,created automatically")
    os.makedirs(output_directory)

output_filepath = os.path.join(output_directory, os.path.basename(${VAL}))

para_model_convert["${CONFIGA}"] = output_filepath`)
        }

    }
    //% block="完成模型转换参数设置，进行一次模型转换" blockType="command"
    export function MMEdu_Init_(parameter: any, block: any){
        Generator.addCode(`mmdeu_model.convert(**para_model_convert)`)
    }

    function replaceQuotationMarks(str:string){
        str=str.replace(/"/g, ""); //去除所有引号
        return str
}
        //% block="数据推理" blockType="tag"
        export function tagtests() {}
    //% block="XEduHub初始化 定义任务名[OBJ] 选择[MODULE]模型" blockType="command" 
    //% OBJ.shadow="normal"    OBJ.defl=task1
    //% MODULE.shadow="dropdownRound"    MODULE.options=MODULE
    export function XEduHub_main_init(parameter: any, block: any){
        let OBJ = parameter.OBJ.code;
        let MODULE = parameter.MODULE.code;

        let boardmenutype=parameter.MODULE.parType
        //console.log(boardmenutype)
        Generator.addInitHeader(`initpara${OBJ}`,`para_${OBJ} = {}`)

        if(boardmenutype.match("nick-cv_collect_train_inference-thirdex.menu.XEduHub_main_init.MODULEMenu")!=null){
            if(MODULE.includes('yikshing')){
                Generator.addCode(`init_para_${OBJ} = {"repo":"${MODULE}"}`)
            }else{
                Generator.addCode(`init_para_${OBJ} = {"task":"${MODULE}"}`)
            }
            
        }else{
            Generator.addCode(`init_para_${OBJ} = {"task":${MODULE}}`)  
        }


    }

    //% block="设置任务[OBJ]的初始化高级参数[PARAM] 为[VAL]" blockType="command" 
    //% OBJ.shadow="normal"    OBJ.defl=task1
    //% PARAM.shadow="dropdownRound"    PARAM.options=PARAM
    //% VAL.shadow="normal"    VAL.defl=""
    export function XEduHub_main_init_set(parameter: any, block: any){
        let OBJ = parameter.OBJ.code;
        let PARAM = parameter.PARAM.code;
        let VAL = parameter.VAL.code;

        let boardmenutype=parameter.PARAM.parType
        
        if(PARAM=="download_path"){
            VAL =checkQuotes(VAL)
            VAL = `r${VAL}`
        }else if(PARAM=="checkpoint"){
            VAL =checkQuotes(VAL)
        }
        console.log(PARAM)
        if(boardmenutype.match("nick-cv_collect_train_inference-thirdex.menu.XEduHub_main_init_set.PARAM")!=null){
            if(PARAM.includes('repo')){
            Generator.addCode(`init_para_${OBJ}["${PARAM}"] = '${VAL}'`)
            }else{
                Generator.addCode(`init_para_${OBJ}["${PARAM}"] = ${VAL}`)
            }
        }else{
            Generator.addCode(`init_para_${OBJ}[${PARAM}] = ${VAL}`)
        }


    }

    
    //% block="任务[OBJ] 完成初始化" blockType="command" 
    //% OBJ.shadow="normal"    OBJ.defl=task1
    export function XEduHub_main_init_end(parameter: any, block: any){
        let OBJ = parameter.OBJ.code;
        Generator.addImport("from XEdu.hub import Workflow as wf\nimport os");
        Generator.addCode(`${OBJ} = wf(**init_para_${OBJ})`)

    }
    
    
    //% block="---"
    export function noteSep2() {

    }
    


    //% block="设置任务[OBJ]的推理参数[CONFIG]为[VAL]" blockType="command"
    //% OBJ.shadow="normal"    OBJ.defl=task1
    //% CONFIG.shadow="dropdownRound"    CONFIG.options=CONFIG
    //% VAL.shadow="normal"    VAL.defl=""
    export function XEduHub_set_tuili(parameter: any, block: any){
        let OBJ = parameter.OBJ.code;
        let CONFIG = parameter.CONFIG.code;
        let boardmenutype=parameter.CONFIG.parType
        //console.log(boardmenutype)
        let VAL = parameter.VAL.code;
        

        if(CONFIG=="data"){
            VAL =addStrQuotation(VAL)
            if(VAL.toLowerCase().includes('wav')||VAL.toLowerCase().includes('mp3')){
                VAL = `"${VAL}"`
            }
        }else if(CONFIG=="img_type"){
            console.log(VAL)
            if(VAL=='pil'||VAL=='cv2'){
                VAL = `"${VAL}"`
            }
        }

        if(boardmenutype.match("nick-cv_collect_train_inference-thirdex.menu.XEduHub_set_tuili.CONFIGMenu")!=null){
            Generator.addCode(`para_${OBJ}["${CONFIG}"] = ${VAL}`)
        }else{
            Generator.addCode(`para_${OBJ}[${CONFIG}] = ${VAL}`)
        }

    }




    //% block="任务[OBJ]完成推理设置 进行一次推理" blockType="command"
    //% OBJ.shadow="normal"    OBJ.defl=task1
    export function XEduHub_main_tuili(parameter: any, block: any){
        let OBJ = parameter.OBJ.code;
        Generator.addImport("import re");

        //Generator.addCode(`rea_result_${OBJ}= ${OBJ}.inference(**para_${OBJ})`)
        Generator.addImport("from XEdu.hub import Workflow as wf\nimport os");

        Generator.addCode(`
if '${OBJ}' in globals() or '${OBJ}' in locals():
    rea_result_${OBJ} = ${OBJ}.inference(**para_${OBJ})
else:
    print("init",'${OBJ}')
    ${OBJ} = wf(**init_para_${OBJ})
    rea_result_${OBJ} = ${OBJ}.inference(**para_${OBJ})
`)
    }
    //% block="---"
    export function noteSep() {

    }
    //% block="获取任务[OBJ]的推理原始输出" blockType="reporter"
    //% OBJ.shadow="normal"    OBJ.defl=task1
    export function XEduHub_main_output(parameter: any, block: any){
        let OBJ = parameter.OBJ.code;
        Generator.addCode(`rea_result_${OBJ}`)
    }

    //% block="获取任务[OBJ]原始输出中[OUTPUT]" blockType="reporter"
    //% OBJ.shadow="normal"    OBJ.defl=task1
    //% OUTPUT.shadow="dropdown"    OUTPUT.options=OUTPUT
    export function XEduHub_main_output_get_key(parameter: any, block: any){
        let OBJ = parameter.OBJ.code;
        let OUTPUT = parameter.OUTPUT.code;
        Generator.addDeclaration("XEduHub_main_output_getkey",`
def valve_getkey(result_val,result_key):
    val_len = len(result_val)
    if val_len<1:
        raise ValueError("Error:推理结果为空，请检查传入的图像或推理参数是否有问题。")
    if val_len==1 and result_key==1:
        raise ValueError("Error:推理结果中无图像，请检查推理参数中img_type项。")
    try: 
        return result_val[result_key]
    except Exception as e:
        raise ValueError(f"Error: 从推理原始结果中取值错误。result_val:{result_val}, result_key:{result_key}。\\nException:{e} ")
`)
        
       
            Generator.addCode(`valve_getkey(rea_result_${OBJ},${OUTPUT})`)
        
    }


    //% block="---"
    export function noteSep4() {

    }

    //% block="将任务[OBJ]的推理结果格式化" blockType="command"
    //% OBJ.shadow="normal"    OBJ.defl=task1
    export function XEduHub_main_format_output(parameter: any, block: any){
        let OBJ = parameter.OBJ.code;
        Generator.addImport("import sys");
        /*
        Generator.addDeclaration("XEduHub_main_format_output",`
def get_format_output(result_input, result_index):
    try:
        # 尝试返回请求的键对应的值
        return result_input[str(result_index)]
    except KeyError:
        # 如果键不存在于字典中，则捕获KeyError
        return f"KeyError: '{result_index}' 不是有效的键"
    except TypeError:
        # 如果提供的索引不是整数，则捕获TypeError
        return "TypeError: 格式化异常"
`)*/
        Generator.addDeclaration("XEduHub_main_format_output",`
def format_valve_output(task):
    try:
        output_result = ""
        output_result = task.format_output(lang="zh")
        return output_result
    except AttributeError:
        return "AttributeError: 请检查输入数据是否正确"`)
  
        Generator.addCode(`output_result_${OBJ} = format_valve_output(${OBJ})`)

    }

    //% block="获取任务[OBJ]格式化后的所有结果" blockType="reporter"
    //% OBJ.shadow="normal"    OBJ.defl=task1
    export function XEduHub_main_get_format_output(parameter: any, block: any){
        let OBJ = parameter.OBJ.code;
        Generator.addCode(`output_result_${OBJ}`)
    }

    //% block="获取任务[OBJ]格式化后的结果中[KEY]的值" blockType="reporter"
    //% OBJ.shadow="normal"    OBJ.defl=task1
    //% KEY.shadow="string"    KEY.defl="分数"
    export function XEduHub_main_get_format_output_getkey(parameter: any, block: any){
        let OBJ = parameter.OBJ.code;
        let KEY = parameter.KEY.code;
       
            Generator.addCode(`output_result_${OBJ}[${KEY}]`)
        
    }



        //% block="---"
        export function noteSep3() {

        }
    //% block="显示任务[OBJ]的结果可视化图片" blockType="command"
    //% OBJ.shadow="normal"    OBJ.defl=task1
    export function XEduHub_main_show(parameter: any, block: any){
        let OBJ = parameter.OBJ.code;
        Generator.addCode(`${OBJ}.show(rea_result_${OBJ})`)
    }


    //% block="保存任务[OBJ]的推理结果图片到[DIR]" blockType="command"
    //% OBJ.shadow="normal"    OBJ.defl=task1
    //% DIR.shadow="string"    DIR.defl='cls_result.jpg'
    export function XEduHub_main_save(parameter: any, block: any){
        let OBJ = parameter.OBJ.code;
        let DIR = parameter.DIR.code;
        Generator.addCode(`${OBJ}.save(rea_result_${OBJ},${DIR})`)
    }






        function addStrQuotation(input_str: string): string {
            //后缀为图片的增加引号
            const dotIndex = input_str.lastIndexOf('.');
            if (dotIndex === -1) {
                return input_str;
            }
            const substringAfterDot = input_str.slice(dotIndex + 1);
            if (substringAfterDot === 'png' || substringAfterDot === 'jpg'){
                return `"${input_str}"`;
            }
            else{
                return input_str;
            }

        }
        //检查是否引号结束
        function checkQuotes(inputstr: string): string {
            const firstChar = inputstr.charAt(0);
            const lastChar = inputstr.charAt(inputstr.length - 1);
          
            if( (firstChar === "'" || firstChar === '"') && firstChar === lastChar){
                return inputstr
            }else{
                return `"${inputstr}"`
            }

          }
}